package com.mtons.mblog.modules.service.impl;

import com.mtons.mblog.base.lang.Consts;
import com.mtons.mblog.modules.data.NavTypeVO;
import com.mtons.mblog.modules.data.NavVO;
import com.mtons.mblog.modules.entity.Channel;
import com.mtons.mblog.modules.entity.Nav;
import com.mtons.mblog.modules.entity.NavType;
import com.mtons.mblog.modules.repository.NavRepository;
import com.mtons.mblog.modules.repository.NavTypeRepository;
import com.mtons.mblog.modules.service.NavService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.persistence.criteria.Predicate;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@Transactional(readOnly = true)
public class NavServiceImpl implements NavService {
	@Autowired
	private NavRepository navRepository;
	@Autowired
	private NavTypeRepository navTypeRepository;

	@Override
	public Page<NavTypeVO> navTypeList(String name, Pageable pageable, Boolean nav) {
		Page<NavType> page = navTypeRepository.findAll((root, query, builder) -> {
			Predicate predicate = builder.conjunction();
			if (!StringUtils.isEmpty(name)) {
				predicate.getExpressions().add(builder.like(root.get("name").as(String.class), "%" + name + "%"));
			}
			return predicate;
		}, pageable);
		List<NavTypeVO> list = new ArrayList<NavTypeVO>();
		page.getContent().forEach(navType -> {
			NavTypeVO vo = new NavTypeVO();
			BeanUtils.copyProperties(navType, vo);
			if(nav) {
				List<Nav> navs = navRepository.findAll((root, query, builder) -> {
					Predicate predicate = builder.conjunction();
					predicate.getExpressions().add(builder.equal(root.get("navTypeId").as(Integer.class), navType.getId()));
					return predicate;
				}, Sort.by(Sort.Direction.DESC, "weight"));
				vo.setNavs(navs);
			}
			list.add(vo);
		});
		return new PageImpl<>(list, pageable, page.getTotalElements());
	}

	@Override
	public Page<NavVO> navList(String name, Integer typeId, Pageable pageable) {
		Page<Nav> page = navRepository.findAll((root, query, builder) -> {
			Predicate predicate = builder.conjunction();
			if (!StringUtils.isEmpty(name)) {
				predicate.getExpressions().add(builder.like(root.get("name").as(String.class), "%" + name + "%"));
			}
			if (typeId != null && typeId > 0) {
				predicate.getExpressions().add(builder.equal(root.get("navTypeId").as(Integer.class), typeId));
			}
			return predicate;
		}, pageable);
		
		List<NavType> types = navTypeRepository.findAll();
		Map<Integer, String> map = types.stream().collect(Collectors.toMap(NavType::getId, NavType::getName));
		
		List<NavVO> list = new ArrayList<NavVO>();
		page.getContent().forEach(nav -> {
			NavVO vo = new NavVO();
			BeanUtils.copyProperties(nav, vo);
			vo.setTypeName(vo.getNavTypeId() != 0 ? map.get(vo.getNavTypeId()) : null);
			list.add(vo);
		});
		return new PageImpl<NavVO>(list, pageable, page.getTotalElements());
	}

	@Override
	public List<NavType> findAll() {
		return navTypeRepository.findAll();
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navTypeDelete(Integer id) {
		navTypeRepository.deleteById(id);
	}

	@Override
	public NavTypeVO getById(Integer id) {
		Optional<NavType> type = navTypeRepository.findById(id);
		NavTypeVO vo = new NavTypeVO();
		BeanUtils.copyProperties(type.get(), vo);
		return vo;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navTypeUpdate(NavType view) {
		Optional<NavType> optional = navTypeRepository.findById(view.getId());
		NavType po = optional.orElse(new NavType());
		BeanUtils.copyProperties(view, po);
		if(!po.getLogo().endsWith("fa-fw")) {
			po.setLogo(po.getLogo() + " fa-fw");
		}
		navTypeRepository.save(po);
	}
	
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navTypeWeight(Integer id) {
		NavType po = navTypeRepository.findById(id).get();
		int max = navTypeRepository.maxWeight() + 1;
		po.setWeight(max);
		navTypeRepository.save(po);
	}

	@Override
	public Nav getNavById(Integer id) {
		Optional<Nav> nav = navRepository.findById(id);
		return nav.get();
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navUpdate(Nav view) {
		Optional<Nav> optional = navRepository.findById(view.getId());
		Nav po = optional.orElse(new Nav());
		BeanUtils.copyProperties(view, po);
		navRepository.save(po);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navWeight(Integer id, Integer typeId) {
		Nav po = navRepository.findById(id).get();
		int max = navRepository.maxWeight(typeId) + 1;
		po.setWeight(max);
		navRepository.save(po);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void navDelete(Integer id) {
		navRepository.deleteById(id);
		// TODO 修改分类
	}
}
